package constructor;

/**
 * 使用Builder模式创建对象示例
 * 
 * Builder模式是一种创建型设计模式，它允许你分步骤创建复杂对象。
 * 该模式让你可以使用相同的创建代码生成不同类型和形式的对象。
 * 
 * 适用场景：
 * 1. 当对象的构造函数参数较多时，使用Builder模式可以让代码更易读和维护
 * 2. 当需要创建不可变对象，但构造过程需要多个步骤时
 * 3. 当想要避免重叠构造函数（telescoping constructor）模式时
 */
public class BuilderDemo {
    private final String name;
    private final int age;
    private final String email;
    private final String phone;
    private final String address;
    private final String company;
    private final boolean isMarried;
    
    // 私有构造函数，只能通过Builder创建对象
    private BuilderDemo(Builder builder) {
        this.name = builder.name;
        this.age = builder.age;
        this.email = builder.email;
        this.phone = builder.phone;
        this.address = builder.address;
        this.company = builder.company;
        this.isMarried = builder.isMarried;
    }
    
    // Getter方法
    public String getName() {
        return name;
    }
    
    public int getAge() {
        return age;
    }
    
    public String getEmail() {
        return email;
    }
    
    public String getPhone() {
        return phone;
    }
    
    public String getAddress() {
        return address;
    }
    
    public String getCompany() {
        return company;
    }
    
    public boolean isMarried() {
        return isMarried;
    }
    
    // 注意：没有setter方法，这保证了对象的不可变性
    
    @Override
    public String toString() {
        return "Person{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", email='" + email + '\'' +
                ", phone='" + phone + '\'' +
                ", address='" + address + '\'' +
                ", company='" + company + '\'' +
                ", isMarried=" + isMarried +
                '}';
    }
    
    /**
     * 静态内部类Builder
     * 提供链式调用来设置对象的各种属性
     */
    public static class Builder {
        // 必需参数
        private String name;
        
        // 可选参数，初始化为默认值
        private int age = 0;
        private String email = "";
        private String phone = "";
        private String address = "";
        private String company = "";
        private boolean isMarried = false;
        
        /**
         * 构造函数，初始化必需参数
         * @param name 姓名（必需参数）
         */
        public Builder(String name) {
            this.name = name;
        }
        
        /**
         * 设置年龄
         * @param age 年龄
         * @return Builder实例，支持链式调用
         */
        public Builder age(int age) {
            this.age = age;
            return this;
        }
        
        /**
         * 设置邮箱
         * @param email 邮箱地址
         * @return Builder实例，支持链式调用
         */
        public Builder email(String email) {
            this.email = email;
            return this;
        }
        
        /**
         * 设置电话号码
         * @param phone 电话号码
         * @return Builder实例，支持链式调用
         */
        public Builder phone(String phone) {
            this.phone = phone;
            return this;
        }
        
        /**
         * 设置地址
         * @param address 地址
         * @return Builder实例，支持链式调用
         */
        public Builder address(String address) {
            this.address = address;
            return this;
        }
        
        /**
         * 设置公司
         * @param company 公司名称
         * @return Builder实例，支持链式调用
         */
        public Builder company(String company) {
            this.company = company;
            return this;
        }
        
        /**
         * 设置婚姻状态
         * @param isMarried 婚姻状态
         * @return Builder实例，支持链式调用
         */
        public Builder isMarried(boolean isMarried) {
            this.isMarried = isMarried;
            return this;
        }
        
        /**
         * 构建最终对象
         * @return 创建的Person对象
         */
        public BuilderDemo build() {
            // 可以在这里添加参数验证逻辑
            if (name == null || name.isEmpty()) {
                throw new IllegalArgumentException("姓名不能为空");
            }
            
            return new BuilderDemo(this);
        }
    }
    
    /**
     * 主方法，演示Builder模式的使用
     */
    public static void main(String[] args) {
        System.out.println("=== Builder模式创建对象示例 ===\n");
        
        // 使用Builder创建对象，只设置必需参数
        System.out.println("1. 只设置必需参数:");
        BuilderDemo person1 = new BuilderDemo.Builder("张三").build();
        System.out.println(person1);
        System.out.println();
        
        // 使用Builder创建对象，设置部分可选参数
        System.out.println("2. 设置部分可选参数:");
        BuilderDemo person2 = new BuilderDemo.Builder("李四")
                .age(28)
                .email("lisi@example.com")
                .build();
        System.out.println(person2);
        System.out.println();
        
        // 使用Builder创建对象，设置所有参数
        System.out.println("3. 设置所有参数:");
        BuilderDemo person3 = new BuilderDemo.Builder("王五")
                .age(32)
                .email("wangwu@example.com")
                .phone("13800138000")
                .address("北京市朝阳区某某街道")
                .company("某某科技有限公司")
                .isMarried(true)
                .build();
        System.out.println(person3);
        System.out.println();
        
        // 演示链式调用的灵活性
        System.out.println("4. 链式调用的灵活性:");
        BuilderDemo person4 = new BuilderDemo.Builder("赵六")
                .company("某某集团")
                .isMarried(false)
                .phone("13900139000")
                .age(25)
                .email("zhaoliu@example.com")
                .address("上海市浦东新区某某路")
                .build();
        System.out.println(person4);
        System.out.println();
        
        // 演示参数验证
        System.out.println("5. 参数验证示例:");
        try {
            BuilderDemo person5 = new BuilderDemo.Builder("")
                    .age(25)
                    .build();
        } catch (IllegalArgumentException e) {
            System.out.println("捕获异常: " + e.getMessage());
        }
        
        // 演示不可变性
        System.out.println("\n=== 不可变对象特性演示 ===");
        System.out.println("创建的对象无法修改其属性，因为没有提供setter方法");
        System.out.println("例如，无法执行 person1.setName(\"新名字\"); 这样的操作");
        System.out.println("如果需要修改，必须创建一个新的对象");
    }
}